package com.kgis.map.geometry {
    import com.kgis.map.Map;
    import com.kgis.map.common.enum.GeoTypeEnum;
    import com.kgis.map.common.util.Evals;
    import com.kgis.map.common.util.GMath;
    import com.kgis.map.feature.Feature;
    import com.kgis.map.geometry.basetype.Extent;
    import com.kgis.map.geometry.basetype.Location;
    import com.kgis.map.style.IStyle;
    import com.kgis.map.style.PolygonStyle;
    import flash.display.Sprite;
    import mx.collections.ArrayCollection;
    import mx.controls.Alert;
    import com.kgis.map.geometry.AbstractGeometry;
    import com.kgis.map.geometry.ArcGeometry;
    import com.kgis.map.geometry.IAreaGeometry;
    import com.kgis.map.geometry.IGeometry;
    import com.kgis.map.geometry.ILineComposeGeometry;
    import com.kgis.map.geometry.ILineGeometry;
    import com.kgis.map.geometry.LineComposeGeometry;
    import com.kgis.map.geometry.PointGeometry;
    import com.kgis.map.geometry.PolylineGeometry;

    [Bindable]
    [RemoteClass(alias="com.kgis.map.model.geometry.PolygonGeometry")]
    /**
     * 简单面
     */
    public class PolygonGeometry extends AbstractGeometry implements ILineComposeGeometry, IAreaGeometry {
        private var _lineList:ArrayCollection = null;

        public function PolygonGeometry() {
            super();
        }

        /**
         * 绘制面
         */
        override public function draw(sprite:Sprite, geoStyle:IStyle, map:Map):void {
            var nFillColor:uint = 0xFF0000;
            var nFillAlpha:Number = 0.5;
            var nEdgeWidth:Number = 1.0;
            var nEdgeColor:uint = 0x6CDD83;
            var nEdgeAlpha:Number = 1.0;

            if (!sprite) {
                trace("polygon sprite为空!");
                return;
            }
            var fea:Feature = sprite as Feature;
            if (!this.isValid()) {
                trace("面几何体不符合规范,polygon objectid=" + fea.objectId.toString());
                return;
            }
            if (!map) {
                trace("map为空,polygon objectid=" + fea.objectId.toString());
                return;
            }

            if (!geoStyle) {
                trace("geoStyle为空,polygon objectid=" + fea.objectId.toString());
                return;
            }

            var polygonStyle:PolygonStyle = geoStyle as PolygonStyle;

            if (!(polygonStyle is PolygonStyle)) {
                trace("面图形数据有误：objectid=" + fea.objectId.toString() + ",layerid=" + fea.layer.id.toString());
                return;
            }

            nFillColor = polygonStyle.fillColor;
            nFillAlpha = polygonStyle.fillAlpha;

            var tempWidth:String;
            if (polygonStyle.edgeWidth.length > map.zoom) {
                tempWidth = polygonStyle.edgeWidth[map.zoom];
            }
            else {
                tempWidth = polygonStyle.edgeWidth[0];
            }
            nEdgeWidth = Evals.getSizeByLevel(tempWidth, map.zoom);

            nEdgeColor = polygonStyle.edgeColor;
            nEdgeAlpha = polygonStyle.edgeAlpha;

            sprite.graphics.clear();
            sprite.graphics.lineStyle(nEdgeWidth, nEdgeColor, nEdgeAlpha, true, "normal", null, null, 3);
            sprite.graphics.beginFill(nFillColor, nFillAlpha);

            var i:int = 0;
            var j:int = 0;

            var subGeo:IGeometry = null;

            var star_commands:Vector.<int> = new Vector.<int>();
            var star_coord:Vector.<Number> = new Vector.<Number>();

            for (i = 0; i < this.lineList.length; i++) {
                subGeo = IGeometry(this.lineList.getItemAt(i));

                if (subGeo.getGeometryType() == GeoTypeEnum.POLYLINEGEOMETRY) {
                    (subGeo as PolylineGeometry).drawPolyline(map, i, star_commands, star_coord);
                }
                else if (subGeo.getGeometryType() == GeoTypeEnum.ARCGEOMETRY) {
                    trace("画弧");
                }
            }
            sprite.graphics.drawPath(star_commands, star_coord);

            //编辑状态显示锚点
            if (fea.editing) {
                drawAnchorPoint(sprite, map);
            }

        }

        /**
         * 画锚点
         */
        private function drawAnchorPoint(sprite:Sprite, map:Map):void {
            var i:int = 0;
            var j:int = 0;
            var subGeo:IGeometry = null;
            var pointindex:int = 0;

            for (j = 0; j < this.lineList.length; j++) {
                subGeo = IGeometry(this.lineList.getItemAt(j));
                if (subGeo.getGeometryType() == GeoTypeEnum.POLYLINEGEOMETRY) {
                    (subGeo as PolylineGeometry).drawAnchorPoint(sprite, map, pointindex, false);
                    pointindex = pointindex + (subGeo as PolylineGeometry).pointList.length - 1;
                }
            }
        }

        override public function getExtent():Extent {
            var i:int = 0;
            var geoExtent:Extent = new Extent(0, 0, 0, 0);
            geoExtent.xmax = -999999999;
            geoExtent.xmin = 999999999;
            geoExtent.ymax = -999999999;
            geoExtent.ymin = 999999999;

            var subGeo:IGeometry = null;
            for (i = 0; i < this.lineList.length; i++) {
                subGeo = IGeometry(this.lineList.getItemAt(i));
                if (i == 0) {
                    geoExtent = subGeo.getExtent();
                }
                else {
                    geoExtent.extendFromBounds(subGeo.getExtent());
                }
            }
            return geoExtent;
        }

        override public function getGeometryType():int {
            return GeoTypeEnum.POLYGONGEOMETRY;
        }

        public function get lineList():ArrayCollection {
            if (_lineList == null) {
                _lineList = new ArrayCollection();
            }
            return _lineList;
        }

        public function set lineList(value:ArrayCollection):void {
            _lineList = value;
        }

        /**
         * 判断参数几何体是否与当前多边形相交
         * @param geom  参数几何体    支持点、折线段、普通多边形
         * @param delta  容差
         */
        public function intersects(geom:IGeometry, delta:Number = 0.00001):Boolean {
            if (!geom) {
                return false;
            }
            var i:Number = 0;
            var j:Number = 0;

            if (geom is PointGeometry) {
                return this.pointInPolygon(geom as PointGeometry) || this.pointOnEdge(geom as PointGeometry, delta);
            }
            else if (geom is PolylineGeometry) {
                //线只要有一个点在多边形内部就算相交
                var polylinetmp:PolylineGeometry = geom as PolylineGeometry;
                for (i = 0; i < polylinetmp.pointList.length; i++) {
                    if (this.pointInPolygon(polylinetmp.pointList.getItemAt(i) as PointGeometry)) {
                        return true;
                    }
                }

            }
            else if (geom is PolygonGeometry) {
                //多边形与多边形的是否有相交
                var polygon:PolygonGeometry = geom as PolygonGeometry;
                for (i = 0; i < this.lineList.length; i++) {
                    var polyline:PolylineGeometry = this.lineList.getItemAt(i) as PolylineGeometry;

                    for (j = 0; j < polyline.pointList.length; j++) {
                        if (polygon.pointInPolygon(polyline.pointList.getItemAt(j) as PointGeometry) || polygon.pointOnEdge(polyline.pointList.getItemAt(j) as PointGeometry, delta)) {
                            return true;
                        }
                    }
                }


                for (i = 0; i < polygon.lineList.length; i++) {
                    polyline = polygon.lineList.getItemAt(i) as PolylineGeometry;

                    for (j = 0; j < polyline.pointList.length; j++) {
                        if (this.pointInPolygon(polyline.pointList.getItemAt(j) as PointGeometry) || this.pointOnEdge(polyline.pointList.getItemAt(j) as PointGeometry, delta)) {
                            return true;
                        }
                    }
                }

            }

            return false;

        }

        /**
         * 判断点是否在当前面内
         * @param pointgeom  点
         */
        public function pointInPolygon(geom:PointGeometry):Boolean {
            if (!geom) {
                return false;
            }
            var i:Number = 0;
            var j:Number = 0;
            var res:Boolean;
            for (i = 0; i < this.lineList.length; i++) {
                var polyline:PolylineGeometry = this.lineList.getItemAt(i) as PolylineGeometry;
                for (j = 0; j < polyline.pointList.length - 1; j++) {
                    if (i == 0 && j == 0) {
                        res = GMath.leftSide(polyline.pointList.getItemAt(j).x, polyline.pointList.getItemAt(j).y, polyline.pointList.getItemAt(j + 1).x, polyline.pointList.getItemAt(j + 1).y, geom.x, geom.y);
                    }
                    else {
                        if (res != GMath.leftSide(polyline.pointList.getItemAt(j).x, polyline.pointList.getItemAt(j).y, polyline.pointList.getItemAt(j + 1).x, polyline.pointList.getItemAt(j + 1).y, geom.x, geom.y)) {
                            return false;
                        }
                    }
                }
            }

            return true;
        }

        /**
         * 判断点是否在当前面的边线上
         * @param pointgeom  点
         * @param delta  容差
         */
        public function pointOnEdge(geom:PointGeometry, delta:Number = 0.00001):Boolean {
            if (!geom) {
                return false;
            }
            var i:Number = 0;
            for (i = 0; i < this.lineList.length; i++) {
                var polyline:PolylineGeometry = this.lineList.getItemAt(i) as PolylineGeometry;
                if (polyline.pointOnLine(geom, delta)) {
                    return true;
                }
            }
            return false;
        }

        override public function getLabelLocation():Location {
            //取多边形的质心
            return GMath.polygonCentroid(this);
        }

        override public function getTolerancePoint(mousePoint:PointGeometry, distance:Number, snapPoint:PointGeometry):int {
            //支持简单多义线的捕捉，关于弧、其它复杂组合图形后期再支持
            var polyLine:PolylineGeometry;
            for each (var line:ILineGeometry in lineList) {
                if (line is PolylineGeometry) {
                    polyLine = line as PolylineGeometry;
                    return polyLine.getTolerancePoint(mousePoint, distance, snapPoint);
                }
                else if (line is ArcGeometry) {

                }
                else if (line is LineComposeGeometry) {

                }
            }
            return 0;

        }

        override public function offset(location:Location):void {
            var polyLine:PolylineGeometry;
            for each (var line:ILineGeometry in this.lineList) {
                if (line is PolylineGeometry) {
                    polyLine = line as PolylineGeometry;
                    polyLine.offset(location);
                        //trace(polyLine.toString());
                }
                else if (line is ArcGeometry) {

                }
                else if (line is LineComposeGeometry) {

                }
            }
        }

        override public function removePoint(point:PointGeometry):void {
            var polyLine:PolylineGeometry;
            var poi:PointGeometry;
            for (var j:Number = 0; j < this.lineList.length; j++) {
                var line:ILineGeometry = this.lineList.getItemAt(j) as ILineGeometry;
                if (line is PolylineGeometry) {
                    polyLine = line as PolylineGeometry;

                    //如果是某条线的首点，则需要在该尾点增加上一条线的倒数第二个点
                    for (var i:Number = 0; i < polyLine.pointList.length; i++) {
                        poi = polyLine.pointList.getItemAt(i) as PointGeometry;
                        if (poi.equals(point)) {
                            if (polyLine.pointList.length < 5) //因为首尾点相同面至少有4个点
                            {
                                Alert.show("This is the minimum number of nodes for feature, can not be deleted", "warning", Alert.OK);
                                return;
                            }
                            if (i == 0) {
                                polyLine.removePointByIndex(0); //当前线删掉首点

                                var polylinetemp:PolylineGeometry;
                                //求上一根线  ，如果不是polyline需要特殊处理，后面处理！！
                                if (j == 0) {
                                    polylinetemp = this.lineList.getItemAt(this.lineList.length - 1) as PolylineGeometry;
                                }
                                else {
                                    polylinetemp = this.lineList.getItemAt(j - 1) as PolylineGeometry;
                                }
                                polylinetemp.removePointByIndex(); //上一根线删除尾点

                                var pointtemp:PointGeometry = polyLine.pointList.getItemAt(0) as PointGeometry;

                                //上一根线增加一个尾点 
                                polylinetemp.addPoint(new PointGeometry(pointtemp.x, pointtemp.y));
                                return;
                            }
                            else {
                                polyLine.removePoint(point);
                                return;
                            }
                        }
                    }

                }
                else if (line is ArcGeometry) {

                }
                else if (line is LineComposeGeometry) {

                }
            }
        }

        override public function isValid():Boolean {
            if (this.lineList.length < 1) {
                return false;
            }
            return true;
        }

        override public function hasPoint(point:PointGeometry):Boolean {
            if (this.lineList == null || !isValid()) {
                return false;
            }
            for (var i:int = 0; i < this.lineList.length; i++) {
                var line:PolylineGeometry = this.lineList.getItemAt(i) as PolylineGeometry;
                if (line.hasPoint(point)) {
                    return true;
                }
            }
            return false;
        }
    }
}